google.maps.LatLng.prototype.distanceFrom = function(newLatLng) {
  //var R = 6371; // km (change this constant to get miles)
  var R = 6378100; // meters
  var lat1 = this.lat();
  var lon1 = this.lng();
  var lat2 = newLatLng.lat();
  var lon2 = newLatLng.lng();
  var dLat = (lat2-lat1) * Math.PI / 180;
  var dLon = (lon2-lon1) * Math.PI / 180;
  var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
    Math.cos(lat1 * Math.PI / 180 ) * Math.cos(lat2 * Math.PI / 180 ) *
    Math.sin(dLon/2) * Math.sin(dLon/2);
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
  var d = R * c;
  return d;
}

// console.log is only available after you have opened the Developer Tools (F12 to toggle it open and closed). 
// Funny thing is that after you've opened it, you can close it, then still post to it via console.log calls, and those will be seen when you reopen it. 
// I'm thinking that is a bug of sorts, and may be fixed, but we shall see.
// I'll probably just use something like this:
function trace(s) {
  try { console.log(s) } catch (e) { ; }
};

myXml = function() {
function read(opts) {

  $.ajax({
    type: "GET",
    url: opts.url,
    dataType: "xml",
    success: opts.callback,
	error: errorfunc,
	cache : false
  });
  
}
function errorfunc(h, sts, no) {
	trace('error reading xml ');
	//console.log('error reading xml '+sts+' '+no);
}
return {
	read:read
}
}();

mysportsAnimation = function () {
var map = null;
var urlkmlfile = '';

var runner = {marker: {}, tick: 200, steps: 0, pause:0, interval :{}, speed: 10, name: '', dist: 0};
var winner = {marker: {}, tick: 200, steps: 0, pause:0, interval: {}, speed: 10, name: 'Fastest', dist:0};
var loser = {marker: {}, tick: 200, steps: 0, pause:0, interval: {}, speed: 10, name: 'Slowest',dist: 0};

var runnerImg = 'runneryellow.png';
var runnerImg2 = 'runner2yellow.png';

var logoUrl = '';
var startPos = null;
var routePoints= [];
var routeLayer = null;
var popUps = [];
var marathon = 42195;
var speedMarkers = [];
var markers = [];
var modalspeed = 15;
var FACTOR= 100; //algemene animatiefactor verkleinen versnelt de animatie, vergroten vertraagt het

var d = new Date();
var sec = d.getTime();
var runnersname = '';
var fDist =0;
var sDist = '';


var initMap = function(opts) {		
		
		if (!opts.logoUrl) {
			alert('You need to add the variable logoUrl to the initMap call...');
			logoUrl = "http://mirror.mysports.tv/runnerstv/bkup/googlemaps/MySports_logo_CMYKzonderPayoff.png";
		}
		else
			logoUrl = opts.logoUrl;
			
		var event = $(opts.runnerEvent).find('eventcode').text();
		
		var latitude = opts.startLatitude;
		var longitude = opts.startLongitude;
		//console.log(latitude);
		//console.log(longitude);
		runner.startPos = new google.maps.LatLng(latitude+0.0001, longitude+0.0001);
		winner.startPos = new google.maps.LatLng(latitude-0.0002, longitude+0.0001);
		loser.startPos = new google.maps.LatLng(latitude-0.0001, longitude-0.0002);
		
		map = new google.maps.Map(document.getElementById("ms-map"), {
				 zoom: 14,
				 tilt: 45,
				 center: new google.maps.LatLng(latitude, longitude),
				 mapTypeId: google.maps.MapTypeId.SATELLITE
		});

		//set de hoogte van de map
		$('#ms-map').css('height', $(document).height() + 'px' );
		$('#ms-map').css('width', $(document).width() + 'px');
		
		routeLayer = new google.maps.KmlLayer(opts.urlkmlfile,
		 {
                      suppressInfoWindows: true,
                      map: map,
                      preserveViewport: true
         });

		//routeLayer.setMap(map);
		//console.log(map.getZoom());
		//console.log(map.getTilt());
		if ($(document).height() < 500)
			map.setZoom(18);
		//alert($(document).height());
		//map.setCenter( new google.maps.LatLng(latitude,longitude) );
		map.setTilt(45);
		
		
	
		var infoControlDiv = document.createElement('DIV');
		var infoControl = new InfoControl(infoControlDiv);
		infoControlDiv.index = 1;
		map.controls[google.maps.ControlPosition.BOTTOM_LEFT].push(infoControlDiv);
		
		
		try {
		var nettime = $(opts.runnerEvent).find('nettime').text();		
		//runner.speed = (marathon/1000) / ( nettime.split(':')[0] * 1 + (nettime.split(':')[0]/60) );
		
		//console.log(runner.speed);
		runnersname = $(opts.runnerEvent).find('name').text();
		runner.name = runnersname;
		
		var htmlStr = "<p>" + runnersname + "<br>" + nettime +"</p>";
	
		$('#dialog > p').html( htmlStr + '<p>' + $(opts.runnerEvent).find('intro').text() + '<br><button id=startbutton>Start</button></p>');
		$('#dialog').dialog({position: ['left','center'], title: $(opts.runnerEvent).find('eventname').text()});
		$('#startbutton').button().click(function() {
							//$('#dialog').dialog("close");
							$('#startbutton').parent().fadeOut('slow');
							laadKmlNogEens(opts);
							});
		}
		catch(e) {
			trace(e.message);
		}
		putRunners();
}

function laadKmlNogEens(opts) {
		//ivm dat ajax niet van een ander domein een bestand kan lezen
		//myXml.read({url: urlkmlfile, callback: parseKml});
		
		myXml.read({url: opts.urlkmlfile, callback: parseKml});
}				

function setLabels() {
   for (var i = 0; i < markers.length; i++) {
          var marker = new google.maps.Marker({
               position: markers[i].pt,
               map: map,
               //shadow: shadow,
               icon: 'empty.png',
               title: markers[i].name,
              zIndex: -5
          });
          var label = new Label({
               map: map
          });
          label.set('zIndex', 1234);
          label.bindTo('position', marker, 'position');
          label.set('text', markers[i].name);
          //label.bindTo('text', marker, 'position');
     }
}

function parseKml(kmlObj) {
	// kml wordt in een json object geladen omdat parseren van het xmlobject met jquery
	// niet helemaal lekker gaat
	// We halen alle placemarks uit de kml die een id hebben, want op die plekken
	// stopt de animatie en wordt er een venster getoond met de content uit het description veld van 
	// een placemark; de descr mag ook html zijn en dus ook een iframe met een videootje
	// de placemark met id=route moet worden overgeslagen omdat dit de routepunten bevat van het evenement
	var jsonObj = $.xml2json(kmlObj);
	var allPlacemarks = jsonObj.Document.Placemark;
	for (i in allPlacemarks) {
		
		if (allPlacemarks[i].id && allPlacemarks[i].id != 'route') {
			popUps.push( {shown: false, pt : new google.maps.LatLng(allPlacemarks[i].Point.coordinates.split(',')[1],allPlacemarks[i].Point.coordinates.split(',')[0]), desc:allPlacemarks[i].description, name:allPlacemarks[i].name  });
			markers.push( {shown: false, pt : new google.maps.LatLng(allPlacemarks[i].Point.coordinates.split(',')[1],allPlacemarks[i].Point.coordinates.split(',')[0]), desc:allPlacemarks[i].description, name:allPlacemarks[i].name });
		}
		
		else 
			if (allPlacemarks[i].id == 'route')
			;
			else
				markers.push( {shown: false, pt : new google.maps.LatLng(allPlacemarks[i].Point.coordinates.split(',')[1],allPlacemarks[i].Point.coordinates.split(',')[0]), desc:allPlacemarks[i].description, name:allPlacemarks[i].name });
		//trace(markers);
		setLabels(markers);
		
		if (allPlacemarks[i].ExtendedData) {
			//console.log(allPlacemarks[i].ExtendedData.Data);
			for (var x in allPlacemarks[i].ExtendedData.Data) {
					if (allPlacemarks[i].ExtendedData.Data[x].name == 'speedrunner') {
						var rspeed = allPlacemarks[i].ExtendedData.Data[x].value.replace(/,/,'.') * 1;
					}
					if (allPlacemarks[i].ExtendedData.Data[x].name == 'speedslowrunner') {
						var lspeed = allPlacemarks[i].ExtendedData.Data[x].value.replace(/,/,'.') * 1;
					}
					if (allPlacemarks[i].ExtendedData.Data[x].name == 'speedfirstrunner') {
						var wspeed = allPlacemarks[i].ExtendedData.Data[x].value.replace(/,/,'.') * 1;
					}			
			}
			
			speedMarkers.push({pt : new google.maps.LatLng(allPlacemarks[i].Point.coordinates.split(',')[1],allPlacemarks[i].Point.coordinates.split(',')[0])
								, runnerspeed: rspeed
								, lowerspeed: lspeed 
								, winnerspeed: wspeed
							});
					
		}
	}
	
	// in popUps heb ik nu alle punten waar een venster moet worden getoond de en animatie moet worden gestopt
	
	// alle punten van de route haal ik er wel uit met jquery, dit lukt dan weer wel
	var cStr = $(kmlObj).find('Linestring > coordinates').text();
	var aCoords = cStr.split(",0.000000");
	var pPrev = null;
	
	var i=0;
	while (i<aCoords.length) {
		try {
			if ($.trim(aCoords[i]).split(",")[0] != '' && $.trim(aCoords[i]).split(",")[1] != '') {
				if (i == 0) {
					var pNew = new google.maps.LatLng($.trim(aCoords[i]).split(",")[1], $.trim(aCoords[i]).split(",")[0]);
				}
				else {
					// Algoritme om extra punten toe te voegen aan rechte stukken zodat de animatie gelijkmatiger loopt
					// Anders verspringt de animatie ineens van het begin van een rechte lijn naar het andere eind
					var pNew = new google.maps.LatLng($.trim(aCoords[i]).split(",")[1], $.trim(aCoords[i]).split(",")[0]);
					var distance = google.maps.geometry.spherical.computeDistanceBetween(pPrev, pNew);
					//console.log(distance);
					var heading = google.maps.geometry.spherical.computeHeading(pPrev,pNew);
					//console.log(heading);

					xPoint = pPrev;
					//trace(distance);
					if (distance >  60) {
						var veelvoud = Math.floor(distance/30);
						for (var x=0; x < veelvoud ; x++) {
							trace('extra pas');
							var xPoint = google.maps.geometry.spherical.computeOffset(xPoint, 30, heading);
							routePoints.push(xPoint);
						}
					}				
				}
				routePoints.push(pNew);
				pPrev = pNew;
			}
		}
		catch(e) {
			trace(e.message);
		}
		i++;
	}
	trace(routePoints.length);
	//console.log(routePoints);
	lekkerlopen();
}

function putRunners() {

initRunner(runner,'runner2red.png','runnerred.png', modalspeed/runner.speed * FACTOR, runnersname + '(YOU)');
initRunner(winner,'runner2yellow.png','runneryellow.png', modalspeed/winner.speed * FACTOR, winner.name);
initRunner(loser,'runner2blue.png','runnerblue.png', modalspeed/loser.speed * FACTOR, loser.name);

};

function initRunner(runner, img2, img, tick, lbl) {
  runner.marker = new google.maps.Marker({
     position: runner.startPos,
     map: map,
     icon: img2,
	 title: lbl,
	 zIndex: -5
  }); 
  
  runner.marker.setAnimation(google.maps.Animation.BOUNCE);
  runner.steps = 0;
  runner.tick = tick;
  runner.pause = false;
  runner.img = img;
  runner.img2 = img2;
  


  var label = new Label({
	   map: map
  });
	  
  label.set('zIndex', 1234);
  label.bindTo('position', runner.marker, 'position');
  label.set('text', lbl);
	  
	  //lab1el.bindTo('text', runner, 'position');
}

var k = 0;
var steps = 0;
var tick=  1; 
var pause = false;
function lekkerlopen() {
	runner.interval = setInterval(function() {  hitMe(runner,true) }, runner.tick);
	winner.interval = setInterval(function() {  hitMe(winner,false) }, winner.tick);
	loser.interval = setInterval(function() {  hitMe(loser,false) }, loser.tick);

}

function hitMe(runner, doPan) {
	if (runner.steps > routePoints.length-2) {
				clearInterval(runner.interval);
	}
	if (!runner.pause) {
		if (runner.marker.getAnimation() != null) {
			runner.marker.setAnimation(null);	
		}
		if (routePoints.length > 0) {		
			// Indien de loper binnen 10 stappen uit de kaart loopt verschuif ik de kaart
			if (doPan && runner.steps % 20 == 0)
				if (runner.steps < routePoints.length-10)
					if ( !map.getBounds().contains(routePoints[runner.steps+8]))
						map.panTo(routePoints[runner.steps+7]);
			
			//wisseling van plaatjes als de looprichting van het ene punt naar het volgende punt verandert
			if (runner.steps < routePoints.length - 2) {
					var heading = google.maps.geometry.spherical.computeHeading(routePoints[runner.steps],routePoints[runner.steps+1]);
					//console.log(heading);
								
					if (heading > 0)
						runner.marker.setIcon(runner.img);
					else
						runner.marker.setIcon(runner.img2);
			}
			
			//kijk of ik moet pauzeren voor een overlayvenster
			if (doPan) {
				testForPopup(routePoints[runner.steps]);
				testForSpeedMarker(routePoints[runner.steps]);
			}
			
			
			if (runner.steps >0 && doPan) {
				fDist += google.maps.geometry.spherical.computeDistanceBetween( routePoints[runner.steps-1], routePoints[runner.steps]);
				//trace(fDist);
				sDist = Math.round(fDist/100)/10;	
				//trace(runner.dist);
			}
			//verplaatst nu echt de loper naar het volgende punt en wacht een tick voor de volgende verplaatsing
			runner.marker.setPosition(routePoints[runner.steps]);
			runner.steps++;	
		} else {
				console.log('geen routepoints');
		}	
	}
}

function testForPopup(p) {	
	if (!runner.pause) {
		for (i in popUps) {
			if (popUps[i].shown) continue;
			//if (p.distanceFrom(popUps[i].pt) < 200) {
			var compDist = sDist + 'k';
			compDist = compDist.replace(/\./,',');
			
			//trace(compDist);
			//trace(popUps[i].name.substr(0, compDist.length));
			//trace(popUps[i].name.indexOf('inish'));
			if (compDist == popUps[i].name.substr(0, compDist.length) || (compDist == '42k' && popUps[i].name.indexOf('inish') > 0)) {
				runner.pause = true;
				winner.pause = true;
				loser.pause = true;
				//console.log('raak: '+ popUps[i].desc);
				var w=0.90*$(document).width();
				var h=0.95*$(document).height();
				$('#popup > p').html("<iframe id='ifr' allowtransparency='true' scrolling='yes' frameborder='0' width='"+ w +"' height='1080' src='"+ popUps[i].desc + "' >If you can see this, your browser doesn't understand iframes.</iframe>");
				popUps[i].shown = true;
				$('#popup').dialog({
									title: 'Your video at ' + popUps[i].name,
									width: w,
									position: ['center','50px'],
									close: function() {
										//console.log('sluit venster; doorlopen...');
										$('#popup > p').children().remove();
										runner.pause = false;
										winner.pause = false;
										loser.pause = false;
									}
									});
									
				//$('iframe').attr('allowTransparency', 'true').attr('frameBorder', '0').attr('scrolling', 'yes');	
				//$('#ifr').contents().scrollTop(100);
			}
		}
	}
}

function testForSpeedMarker(p) {
		for (i in speedMarkers) {
			//console.log(speedMarkers[i]);
			//console.log(i);
			try {
				var distance = google.maps.geometry.spherical.computeDistanceBetween(p, speedMarkers[i].pt);
				//if (p.distanceFrom(speedMarkers[i].pt) < 200) {
				//trace(distance); //nu komt er een snelheidsverandering
				if (distance <100) {
						if (speedMarkers[i].runnerspeed > 0 && runner.tick != speedMarkers[i].runnerspeed/modalspeed * FACTOR) {
								clearInterval(runner.interval);
								runner.tick = modalspeed/speedMarkers[i].runnerspeed * FACTOR;
								runner.interval = setInterval(function() {  hitMe(runner,true) }, runner.tick);
						}
						if (speedMarkers[i].winnerspeed > 0  && winner.tick != speedMarkers[i].winnerspeed/modalspeed * FACTOR) {
								clearInterval(winner.interval);
								winner.tick = modalspeed/speedMarkers[i].winnerspeed * FACTOR;
								winner.interval = setInterval(function() {  hitMe(winner,false) }, winner.tick);
						}
						if (speedMarkers[i].lowerspeed > 0  && loser.tick != speedMarkers[i].lowerspeed/modalspeed * FACTOR) {
								clearInterval(loser.interval);
								loser.tick = modalspeed/speedMarkers[i].lowerspeed * FACTOR;
								loser.interval = setInterval(function() {  hitMe(loser,false) }, loser.tick);
						}
				}
			}
			catch(e) {
					trace(e.message);
			}
		}
}

function InfoControl(controlDiv) {

  // Set CSS styles for the DIV containing the control
  // Setting padding to 5 px will offset the control
  // from the edge of the map.
  controlDiv.style.padding = '5px';

  // Set CSS for the control border.
  var controlUI = document.createElement('DIV');
  controlUI.style.backgroundColor = 'transparent';
  controlUI.style.borderStyle = 'solid';
  controlUI.style.borderWidth = '0px';
  controlUI.style.cursor = 'pointer';
  controlUI.style.textAlign = 'center';
  controlUI.title = 'mysports.tv &copy;2012';
  controlDiv.appendChild(controlUI);

  // Set CSS for the control interior.
  var controlContent = document.createElement('img');
  controlContent.src = logoUrl;
  //controlText.style.fontSize = '120%';
  //controlText.style.paddingLeft = '10em';
  //controlText.style.paddingRight = '10em';
  //controlText.innerHTML = htmlStr;
  controlUI.appendChild(controlContent);
}

return {
		initMap:initMap
		//,animateRunner:animateRunner
	};
}();
